<template>
  <div
      ref="reference"
      tabindex="0"
      @click="handleClick"
      @keydown.esc="handleEscape"
      @keydown.enter="handleEnter"
      @keydown.left="handleArrow($event, 'x', left)"
      @keydown.right="handleArrow($event, 'x', right)"
      @keydown.up="handleArrow($event, 'y', up)"
      @keydown.down="handleArrow($event, 'y', down)"
      @blur="blurColor"
      @focus="focusColor"
  >
    <template v-for="(item, index) in list">
      <div
          :key="item + ':' + index"
          :class="[prefixCls + '-picker-colors-wrapper']">
        <div :data-color-id="index">
          <div
              :style="{background: item}"
              :class="[prefixCls + '-picker-colors-wrapper-color']"
          ></div>
          <div
              :ref="'color-circle-' + index"
              :class="[prefixCls + '-picker-colors-wrapper-circle', hideClass]"></div>
        </div>
      </div>
      <br v-if="lineBreak(list, index)">
    </template>
  </div>
</template>

<script>
  import Emitter from '../../mixins/emitter'
  import HandleEscapeMixin from './handleEscapeMixin'
  import Prefixes from './prefixMixin'
  import { clamp } from './utils'

  export default {
    name: 'RecommendedColors',

    mixins: [Emitter, HandleEscapeMixin, Prefixes],

    props: {
      list: {
        type: Array,
        default: undefined,
      },
    },

    data () {
      const columns = 12
      const rows = Math.ceil(this.list.length / columns)
      const normalStep = 1

      return {
        left: -normalStep,
        right: normalStep,
        up: -normalStep,
        down: normalStep,
        powerKey: 'shiftKey',
        grid: { x: 1, y: 1 },
        rows,
        columns
      }
    },
    computed: {
      hideClass () {
        return `${this.prefixCls}-hide`
      },
      linearIndex () {
        return this.getLinearIndex(this.grid)
      },
      currentCircle () {
        return this.$refs[`color-circle-${this.linearIndex}`][0]
      }
    },
    methods: {
      getLinearIndex (grid) {
        return this.columns * (grid.y - 1) + grid.x - 1
      },
      getMaxLimit (axis) {
        return axis === 'x' ? this.columns : this.rows
      },
      handleArrow (e, axis, direction) {
        e.preventDefault()
        e.stopPropagation()
        this.blurColor()
        const grid = { ...this.grid }
        if (e[this.powerKey]) {
          if (direction < 0) {
            grid[axis] = 1
          } else {
            grid[axis] = this.getMaxLimit(axis)
          }
        } else {
          grid[axis] += direction
        }

        const index = this.getLinearIndex(grid)

        if (index >= 0 && index < this.list.length) {
          this.grid[axis] = clamp(grid[axis], 1, this.getMaxLimit(axis))
        }

        this.focusColor()
      },
      blurColor () {
        this.currentCircle.classList.add(this.hideClass)
      },
      focusColor () {
        this.currentCircle.classList.remove(this.hideClass)
      },
      handleEnter (e) {
        this.handleClick(e, this.currentCircle)
      },
      handleClick (e, circle) {
        e.preventDefault()
        e.stopPropagation()

        this.$refs.reference.focus()

        const target = circle || e.target
        const colorId = target.dataset.colorId || target.parentElement.dataset.colorId

        if (colorId) {
          this.blurColor()
          const id = Number(colorId) + 1
          this.grid.x = id % this.columns || this.columns
          this.grid.y = Math.ceil(id / this.columns)
          this.focusColor()
          this.$emit('picker-color', this.list[colorId])
          this.$emit('change', { hex: this.list[colorId], source: 'hex' })
        }
      },
      lineBreak (list, index) {
        if (!index) {
          return false
        }

        const nextIndex = index + 1

        return nextIndex < list.length && nextIndex % this.columns === 0
      }
    }
  }
</script>
